Seminar "Mastering your Data – from Exploration to Visualization

Getting Started with Data in R

Before we can start exploring data in R, there are some key concepts to understand first:

  1. What are R and RStudio?
  2. How do I code in R?
  3. What are R packages?

1. What are R and RStudio?

Throughout this book, we will assume that you are using R via RStudio. First time users often confuse the two. At its simplest, R is like a car’s engine while RStudio is like a car’s dashboard as illustrated here

Analogy of difference between R and RStudio.

More precisely, R is a programming language that runs computations, while RStudio is an integrated development environment (IDE) that provides an interface by adding many convenient features and tools. So just as the way of having access to a speedometer, rearview mirrors, and a navigation system makes driving much easier, using RStudio’s interface makes using R much easier as well.

Installing R and RStudio

You will first need to download and install both R and RStudio (Desktop version) on your computer. It is important that you install R first and then install RStudio.

  1. You must do this first: Download and install R by going to https://cloud.r-project.org/.
    • If you are a Windows user: Click on “Download R for Windows”, then click on “base”, then click on the Download link.
    • If you are macOS user: Click on “Download R for (Mac) OS X”, then under “Latest release:” click on R-X.X.X.pkg, where R-X.X.X is the version number. For example, the latest version of R as of November 25, 2019 was R-3.6.1.
    • If you are a Linux user: Click on “Download R for Linux” and choose your distribution for more information on installing R for your setup.
  2. You must do this second: Download and install RStudio at https://www.rstudio.com/products/rstudio/download/.
    • Scroll down to “Installers for Supported Platforms” near the bottom of the page.
    • Click on the download link corresponding to your computer’s operating system.

Using R via RStudio

Recall our car analogy from earlier. Much as we don’t drive a car by interacting directly with the engine but rather by interacting with elements on the car’s dashboard, we won’t be using R directly but rather we will use RStudio’s interface. After you install R and RStudio on your computer, you’ll have two new programs (also called applications) you can open. We’ll always work in RStudio and not in the R application. Here shows what icon you should be clicking on your computer.

Icons of R versus RStudio on your computer.

After you open RStudio, you should see something similar to this (Note that slight differences might exist if the RStudio interface is updated after 2019 to not be this by default.)

Note the three panes which are three panels dividing the screen: the console pane, the files pane, and the environment pane. Over the course of this chapter, you’ll come to learn what purpose each of these panes serves.

How do I code in R?

Now that you’re set up with R and RStudio, you are probably asking yourself, “OK. Now how do I use R?”. The first thing to note is that unlike other statistical software programs like Excel, SPSS, or Minitab that provide point-and-click interfaces, R is an interpreted language. This means you have to type in commands written in R code. In other words, you have to code/program in R. Note that we’ll use the terms “coding” and “programming” interchangeably in this book.

While it is not required to be a seasoned coder/computer programmer to use R, there is still a set of basic programming concepts that new R users need to understand. Consequently, while this book is not a book on programming, you will still learn just enough of these basic programming concepts needed to explore and analyze data effectively.

Basic programming concepts and terminology

We now introduce some basic programming concepts and terminology. Instead of asking you to memorize all these concepts and terminology right now, we’ll guide you so that you’ll “learn by doing.” To help you learn, we will always use a different font to distinguish regular text from computer_code. The best way to master these topics is, in our opinions, through deliberate practice with R and lots of repetition.

  • Basics:
    • Console pane: where you enter in commands.
    • Running code: the act of telling R to perform an act by giving it commands in the console.
    • Objects: where values are saved in R. We’ll show you how to assign values to objects and how to display the contents of objects.
    • Data types: integers, doubles/numerics, logicals, and characters. Integers are values like -1, 0, 2, 4092. Doubles or numerics are a larger set of values containing both the integers but also fractions and decimal values like -24.932 and 0.8. Logicals are either TRUE or FALSE while characters are text such as “cancer”, “hospital”, “The patient comes from the city hospital”, and “My name is Peter.” Note that characters are often denoted with the quotation marks around them.
  • Vectors: a series of values.
  • Factors: categorical data are commonly represented in R as factors. Categorical data can also be represented as strings.
  • Data frames: rectangular spreadsheets. They are representations of datasets in R where the rows correspond to observations and the columns correspond to variables that describe the observations.

If you have worked with a spreadsheet such as Excel think the dataframe as the spreadsheet and vectors as the columns.

Errors, warnings, and messages

One thing that intimidates new R and RStudio users is how it reports errors, warnings, and messages. R reports errors, warnings, and messages in a glaring red font, which makes it seem like it is scolding you. However, seeing red text in the console is not always bad.

R will show red text in the console pane in three different situations:

  • Errors: When the red text is a legitimate error, it will be prefaced with “Error in…” and will try to explain what went wrong. Generally when there’s an error, the code will not run. For example, we’ll see in Subsection @ref(package-use) if you see Error in ggplot(...) : could not find function "ggplot", it means that the ggplot() function is not accessible because the package that contains the function (ggplot2) was not loaded with library(ggplot2). Thus you cannot use the ggplot() function without the ggplot2 package being loaded first.
  • Warnings: When the red text is a warning, it will be prefaced with “Warning:” and R will try to explain why there’s a warning. Generally your code will still work, but with some caveats. For example, you will see in Chapter @ref(viz) if you create a scatterplot based on a dataset where two of the rows of data have missing entries that would be needed to create points in the scatterplot, you will see this warning: Warning: Removed 2 rows containing missing values (geom_point). R will still produce the scatterplot with all the remaining non-missing values, but it is warning you that two of the points aren’t there.
  • Messages: When the red text doesn’t start with either “Error” or “Warning”, it’s just a friendly message. You’ll see these messages when you load R packages in the upcoming Subsection @ref(package-loading) or when you read data saved in spreadsheet files with the read_csv() function as you’ll see in Chapter @ref(tidy). These are helpful diagnostic messages and they don’t stop your code from working. Additionally, you’ll see these messages when you install packages too using install.packages() as discussed in Subsection @ref(package-installation).

Remember, when you see red text in the console, don’t panic. It doesn’t necessarily mean anything is wrong. Rather:

  • If the text starts with “Error”, figure out what’s causing it. Think of errors as a red traffic light: something is wrong!
  • If the text starts with “Warning”, figure out if it’s something to worry about. For instance, if you get a warning about missing values in a scatterplot and you know there are missing values, you’re fine. If that’s surprising, look at your data and see what’s missing. Think of warnings as a yellow traffic light: everything is working fine, but watch out/pay attention.
  • Otherwise, the text is just a message. Read it, wave back at R, and thank it for talking to you. Think of messages as a green traffic light: everything is working fine and keep on going!

Tips on learning to code

Learning to code/program is quite similar to learning a foreign language. It can be daunting and frustrating at first. Such frustrations are common and it is normal to feel discouraged as you learn. However, just as with learning a foreign language, if you put in the effort and are not afraid to make mistakes, anybody can learn and improve.

Here are a few useful tips to keep in mind as you learn to program:

  • Remember that computers are not actually that smart: You may think your computer or smartphone is “smart,” but really people spent a lot of time and energy designing them to appear “smart.” In reality, you have to tell a computer everything it needs to do. Furthermore, the instructions you give your computer can’t have any mistakes in them, nor can they be ambiguous in any way.
  • Take the “copy, paste, and tweak” approach: Especially when you learn your first programming language or you need to understand particularly complicated code, it is often much easier to take existing code that you know works and modify it to suit your ends. This is as opposed to trying to type out the code from scratch. We call this the “copy, paste, and tweak” approach. So early on, we suggest not trying to write code from memory, but rather take existing examples we have provided you, then copy, paste, and tweak them to suit your goals. After you start feeling more confident, you can slowly move away from this approach and write code from scratch. Think of the “copy, paste, and tweak” approach as training wheels for a child learning to ride a bike. After getting comfortable, they won’t need them anymore.
  • The best way to learn to code is by doing: Rather than learning to code for its own sake, we find that learning to code goes much smoother when you have a goal in mind or when you are working on a particular project, like analyzing data that you are interested in and that is important to you.
  • Practice is key: Just as the only method to improve your foreign language skills is through lots of practice and speaking, the only method to improving your coding skills is through lots of practice. Don’t worry, however, we’ll give you plenty of opportunities to do so!

What are R packages?

Another point of confusion with many new R users is the idea of an R package. R packages extend the functionality of R by providing additional functions, data, and documentation. They are written by a worldwide community of R users and can be downloaded for free from the internet.

For example, among the many packages we will use in this book are the ggplot2 package, the dplyr package for data wrangling and many others. There are some packages that include several other packages. This is the case with tidyverse, which includes many of the packages needed for the usual data science tasks

A good analogy for R packages is they are like apps you can download onto a mobile phone:

Analogy of R versus R packages.

So R is like a new mobile phone: while it has a certain amount of features when you use it for the first time, it doesn’t have everything. R packages are like the apps you can download onto your phone from Apple’s App Store or Android’s Google Play.

Let’s continue this analogy by considering the Instagram app for editing and sharing pictures. Say you have purchased a new phone and you would like to share a photo you have just taken with friends on Instagram. You need to:

  1. Install the app: Since your phone is new and does not include the Instagram app, you need to download the app from either the App Store or Google Play. You do this once and you’re set for the time being. You might need to do this again in the future when there is an update to the app.
  2. Open the app: After you’ve installed Instagram, you need to open it.

Once Instagram is open on your phone, you can then proceed to share your photo with your friends and family. The process is very similar for using an R package. You need to:

  1. Install the package: This is like installing an app on your phone. Most packages are not installed by default when you install R and RStudio. Thus if you want to use a package for the first time, you need to install it first. Once you’ve installed a package, you likely won’t install it again unless you want to update it to a newer version.
  2. “Load” the package: “Loading” a package is like opening an app on your phone. Packages are not “loaded” by default when you start RStudio on your computer; you need to “load” each package you want to use every time you start RStudio.

Let’s perform these two steps for the tidyverse package that includes many other packages, as ‘ggplot2’ data visualization.

Package installation

  1. Click on the “Packages” tab.
  2. Type the name of the package under “Packages (separate multiple with space or comma):” In this case, type tidyverse.
  3. Click on “Install” next to Update.
  4. Click “Install.”

“Tidyverse package installation”

An alternative but slightly less convenient way to install a package is by typing install.packages("tidyverse") in the console pane of RStudio and pressing Return/Enter on your keyboard. Note you must include the quotation marks around the name of the package.

Much like an app on your phone, you only have to install a package once. However, if you want to update a previously installed package to a newer version, you need to reinstall it by repeating the earlier steps.

Repeat the earlier installation steps, but for the palmerpenguins, NHANES, and janitor packages. This will install the earlier mentioned packages. We’ll use these packages (and more) during the course.

Note that if you’d like your output on your computer to match up exactly with the output presented throughout the book, you may want to use the exact versions of the packages that we used. You can find a full listing of these packages and their versions in Appendix @ref(appendixE). This likely won’t be relevant for novices, but we included it for reproducibility reasons.

Package loading

Recall that after you’ve installed a package, you need to “load it.” In other words, you need to “open it.” We do this by using the library() command.

For example, to load the ggplot2 package, run the following code in the console pane. What do we mean by “run the following code”? Either type or copy-and-paste the following code into the console pane and then hit the Enter key.

library(ggplot2)

If after running the earlier code, a blinking cursor returns next to the > “prompt” sign, it means you were successful and the ggplot2 package is now loaded and ready to use. If, however, you get a red “error message” that reads ...

Error in library(ggplot2) : there is no package called ‘ggplot2’

... it means that you didn’t successfully install it. This is an example of an “error message” . If you get this error message, go back to of Package Installation on R package installation and make sure to install the tidyverse package before proceeding.

Package use

One very common mistake new R users make when wanting to use particular packages is they forget to “load” them first by using the library() command we just saw. Remember: you have to load each package you want to use every time you start RStudio. If you don’t first “load” a package, but attempt to use one of its features, you’ll see an error message similar to:

Error: could not find function

This is a different error message than the one you just saw on a package not having been installed yet. R is telling you that you are trying to use a function in a package that has not yet been “loaded.” R doesn’t know where to find the function you are using. Almost all new users forget to do this when starting out, and it is a little annoying to get used to doing it. However, you’ll remember with practice and after some time it will become second nature for you.

LS0tCnRpdGxlOiAiR2V0dGluZyBTdGFydGVkIHdpdGggRGF0YSBpbiBSIgpvdXRwdXQ6CiAgcGRmX2RvY3VtZW50OiBkZWZhdWx0CiAgaHRtbF9kb2N1bWVudDoKICAgIGRmX3ByaW50OiBwYWdlZAogIGh0bWxfbm90ZWJvb2s6IGRlZmF1bHQKLS0tCgpfU2VtaW5hciAiTWFzdGVyaW5nIHlvdXIgRGF0YSDigJMgZnJvbSBFeHBsb3JhdGlvbiB0byBWaXN1YWxpemF0aW9uXwoKIyBHZXR0aW5nIFN0YXJ0ZWQgd2l0aCBEYXRhIGluIFIgeyNnZXR0aW5nLXN0YXJ0ZWR9CgpCZWZvcmUgd2UgY2FuIHN0YXJ0IGV4cGxvcmluZyBkYXRhIGluIFIsIHRoZXJlIGFyZSBzb21lIGtleSBjb25jZXB0cyB0byB1bmRlcnN0YW5kIGZpcnN0OgoKMS4gV2hhdCBhcmUgUiBhbmQgUlN0dWRpbz8KMS4gSG93IGRvIEkgY29kZSBpbiBSPwoxLiBXaGF0IGFyZSBSIHBhY2thZ2VzPwoKIyMgMS4gV2hhdCBhcmUgUiBhbmQgUlN0dWRpbz8KClRocm91Z2hvdXQgdGhpcyBib29rLCB3ZSB3aWxsIGFzc3VtZSB0aGF0IHlvdSBhcmUgdXNpbmcgUiB2aWEgUlN0dWRpby4gRmlyc3QgdGltZSB1c2VycyBvZnRlbiBjb25mdXNlIHRoZSB0d28uIEF0IGl0cyBzaW1wbGVzdCwgUiBpcyBsaWtlIGEgY2Fy4oCZcyBlbmdpbmUgd2hpbGUgUlN0dWRpbyBpcyBsaWtlIGEgY2Fy4oCZcyBkYXNoYm9hcmQgYXMgaWxsdXN0cmF0ZWQgaGVyZQoKCiFbQW5hbG9neSBvZiBkaWZmZXJlbmNlIGJldHdlZW4gUiBhbmQgUlN0dWRpby5dKC4uL0ZpZ3Mvcl92c19yc3R1ZGlvXzEucG5nKQoKTW9yZSBwcmVjaXNlbHksIFIgaXMgYSBwcm9ncmFtbWluZyBsYW5ndWFnZSB0aGF0IHJ1bnMgY29tcHV0YXRpb25zLCB3aGlsZSBSU3R1ZGlvIGlzIGFuIGludGVncmF0ZWQgZGV2ZWxvcG1lbnQgZW52aXJvbm1lbnQgKElERSkgdGhhdCBwcm92aWRlcyBhbiBpbnRlcmZhY2UgYnkgYWRkaW5nIG1hbnkgY29udmVuaWVudCBmZWF0dXJlcyBhbmQgdG9vbHMuIFNvIGp1c3QgYXMgdGhlIHdheSBvZiBoYXZpbmcgYWNjZXNzIHRvIGEgc3BlZWRvbWV0ZXIsIHJlYXJ2aWV3IG1pcnJvcnMsIGFuZCBhIG5hdmlnYXRpb24gc3lzdGVtIG1ha2VzIGRyaXZpbmcgbXVjaCBlYXNpZXIsIHVzaW5nIFJTdHVkaW/igJlzIGludGVyZmFjZSBtYWtlcyB1c2luZyBSIG11Y2ggZWFzaWVyIGFzIHdlbGwuCgojIyMgIEluc3RhbGxpbmcgUiBhbmQgUlN0dWRpbwoKCllvdSB3aWxsIGZpcnN0IG5lZWQgdG8gZG93bmxvYWQgYW5kIGluc3RhbGwgYm90aCBSIGFuZCBSU3R1ZGlvIChEZXNrdG9wIHZlcnNpb24pIG9uIHlvdXIgY29tcHV0ZXIuIEl0IGlzIGltcG9ydGFudCB0aGF0IHlvdSBpbnN0YWxsIFIgZmlyc3QgYW5kIHRoZW4gaW5zdGFsbCBSU3R1ZGlvLgoKMS4gKipZb3UgbXVzdCBkbyB0aGlzIGZpcnN0OioqIERvd25sb2FkIGFuZCBpbnN0YWxsIFIgYnkgZ29pbmcgdG8gPGh0dHBzOi8vY2xvdWQuci1wcm9qZWN0Lm9yZy8+LiBcaW5kZXh7UiFpbnN0YWxsYXRpb259CiAgICArIElmIHlvdSBhcmUgYSBXaW5kb3dzIHVzZXI6IENsaWNrIG9uICJEb3dubG9hZCBSIGZvciBXaW5kb3dzIiwgdGhlbiBjbGljayBvbiAiYmFzZSIsIHRoZW4gY2xpY2sgb24gdGhlIERvd25sb2FkIGxpbmsuIAogICAgKyBJZiB5b3UgYXJlIG1hY09TIHVzZXI6IENsaWNrIG9uICJEb3dubG9hZCBSIGZvciAoTWFjKSBPUyBYIiwgdGhlbiB1bmRlciAiTGF0ZXN0IHJlbGVhc2U6IiBjbGljayBvbiBSLVguWC5YLnBrZywgd2hlcmUgUi1YLlguWCBpcyB0aGUgdmVyc2lvbiBudW1iZXIuIEZvciBleGFtcGxlLCB0aGUgbGF0ZXN0IHZlcnNpb24gb2YgUiBhcyBvZiBOb3ZlbWJlciAyNSwgMjAxOSB3YXMgUi0zLjYuMS4KICAgICsgSWYgeW91IGFyZSBhIExpbnV4IHVzZXI6IENsaWNrIG9uICJEb3dubG9hZCBSIGZvciBMaW51eCIgYW5kIGNob29zZSB5b3VyIGRpc3RyaWJ1dGlvbiBmb3IgbW9yZSBpbmZvcm1hdGlvbiBvbiBpbnN0YWxsaW5nIFIgZm9yIHlvdXIgc2V0dXAuCjEuICoqWW91IG11c3QgZG8gdGhpcyBzZWNvbmQ6KiogRG93bmxvYWQgYW5kIGluc3RhbGwgUlN0dWRpbyBhdCA8aHR0cHM6Ly93d3cucnN0dWRpby5jb20vcHJvZHVjdHMvcnN0dWRpby9kb3dubG9hZC8+LgogICAgKyBTY3JvbGwgZG93biB0byAiSW5zdGFsbGVycyBmb3IgU3VwcG9ydGVkIFBsYXRmb3JtcyIgbmVhciB0aGUgYm90dG9tIG9mIHRoZSBwYWdlLgogICAgKyBDbGljayBvbiB0aGUgZG93bmxvYWQgbGluayBjb3JyZXNwb25kaW5nIHRvIHlvdXIgY29tcHV0ZXIncyBvcGVyYXRpbmcgc3lzdGVtLiAKICAgIAojIyMgVXNpbmcgUiB2aWEgUlN0dWRpbwoKUmVjYWxsIG91ciBjYXIgYW5hbG9neSBmcm9tIGVhcmxpZXIuIE11Y2ggYXMgd2UgZG9uJ3QgZHJpdmUgYSBjYXIgYnkgaW50ZXJhY3RpbmcgZGlyZWN0bHkgd2l0aCB0aGUgZW5naW5lIGJ1dCByYXRoZXIgYnkgaW50ZXJhY3Rpbmcgd2l0aCBlbGVtZW50cyBvbiB0aGUgY2FyJ3MgZGFzaGJvYXJkLCB3ZSB3b24ndCBiZSB1c2luZyBSIGRpcmVjdGx5IGJ1dCByYXRoZXIgd2Ugd2lsbCB1c2UgUlN0dWRpbydzIGludGVyZmFjZS4gQWZ0ZXIgeW91IGluc3RhbGwgUiBhbmQgUlN0dWRpbyBvbiB5b3VyIGNvbXB1dGVyLCB5b3UnbGwgaGF2ZSB0d28gbmV3ICpwcm9ncmFtcyogKGFsc28gY2FsbGVkICphcHBsaWNhdGlvbnMqKSB5b3UgY2FuIG9wZW4uIFdlJ2xsIGFsd2F5cyB3b3JrIGluIFJTdHVkaW8gYW5kIG5vdCBpbiB0aGUgUiBhcHBsaWNhdGlvbi4gSGVyZSBzaG93cyB3aGF0IGljb24geW91IHNob3VsZCBiZSBjbGlja2luZyBvbiB5b3VyIGNvbXB1dGVyLiAKCiFbSWNvbnMgb2YgUiB2ZXJzdXMgUlN0dWRpbyBvbiB5b3VyIGNvbXB1dGVyLl0oLi4vRmlncy9yX3ZzX3JzdHVkaW8ucG5nKQoKQWZ0ZXIgeW91IG9wZW4gUlN0dWRpbywgeW91IHNob3VsZCBzZWUgc29tZXRoaW5nIHNpbWlsYXIgdG8gdGhpcyAoTm90ZSB0aGF0IHNsaWdodCBkaWZmZXJlbmNlcyBtaWdodCBleGlzdCBpZiB0aGUgUlN0dWRpbyBpbnRlcmZhY2UgaXMgdXBkYXRlZCBhZnRlciAyMDE5IHRvIG5vdCBiZSB0aGlzIGJ5IGRlZmF1bHQuKQohW10oLi4vRmlncy9yc3R1ZGlvLnBuZykKCk5vdGUgdGhlIHRocmVlICpwYW5lcyogd2hpY2ggYXJlIHRocmVlIHBhbmVscyBkaXZpZGluZyB0aGUgc2NyZWVuOiB0aGUgKmNvbnNvbGUgcGFuZSosIHRoZSAqZmlsZXMgcGFuZSosIGFuZCB0aGUgKmVudmlyb25tZW50IHBhbmUqLiBPdmVyIHRoZSBjb3Vyc2Ugb2YgdGhpcyBjaGFwdGVyLCB5b3UnbGwgY29tZSB0byBsZWFybiB3aGF0IHB1cnBvc2UgZWFjaCBvZiB0aGVzZSBwYW5lcyBzZXJ2ZXMuIAoKCiMjIEhvdyBkbyBJIGNvZGUgaW4gUj8geyNjb2RlfQoKTm93IHRoYXQgeW91J3JlIHNldCB1cCB3aXRoIFIgYW5kIFJTdHVkaW8sIHlvdSBhcmUgcHJvYmFibHkgYXNraW5nIHlvdXJzZWxmLCAiT0suIE5vdyBob3cgZG8gSSB1c2UgUj8iLiBUaGUgZmlyc3QgdGhpbmcgdG8gbm90ZSBpcyB0aGF0IHVubGlrZSBvdGhlciBzdGF0aXN0aWNhbCBzb2Z0d2FyZSBwcm9ncmFtcyBsaWtlIEV4Y2VsLCBTUFNTLCBvciBNaW5pdGFiIHRoYXQgcHJvdmlkZSBbcG9pbnQtYW5kLWNsaWNrXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Qb2ludF9hbmRfY2xpY2spIGludGVyZmFjZXMsIFIgaXMgYW4gW2ludGVycHJldGVkIGxhbmd1YWdlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9JbnRlcnByZXRlZF9sYW5ndWFnZSkuIFRoaXMgbWVhbnMgeW91IGhhdmUgdG8gdHlwZSBpbiBjb21tYW5kcyB3cml0dGVuIGluICpSIGNvZGUqLiBJbiBvdGhlciB3b3JkcywgeW91IGhhdmUgdG8gY29kZS9wcm9ncmFtIGluIFIuIE5vdGUgdGhhdCB3ZSdsbCB1c2UgdGhlIHRlcm1zICJjb2RpbmciIGFuZCAicHJvZ3JhbW1pbmciIGludGVyY2hhbmdlYWJseSBpbiB0aGlzIGJvb2suCgpXaGlsZSBpdCBpcyBub3QgcmVxdWlyZWQgdG8gYmUgYSBzZWFzb25lZCBjb2Rlci9jb21wdXRlciBwcm9ncmFtbWVyIHRvIHVzZSBSLCB0aGVyZSBpcyBzdGlsbCBhIHNldCBvZiBiYXNpYyBwcm9ncmFtbWluZyBjb25jZXB0cyB0aGF0IG5ldyBSIHVzZXJzIG5lZWQgdG8gdW5kZXJzdGFuZC4gQ29uc2VxdWVudGx5LCB3aGlsZSB0aGlzIGJvb2sgaXMgbm90IGEgYm9vayBvbiBwcm9ncmFtbWluZywgeW91IHdpbGwgc3RpbGwgbGVhcm4ganVzdCBlbm91Z2ggb2YgdGhlc2UgYmFzaWMgcHJvZ3JhbW1pbmcgY29uY2VwdHMgbmVlZGVkIHRvIGV4cGxvcmUgYW5kIGFuYWx5emUgZGF0YSBlZmZlY3RpdmVseS4KCgojIyMgQmFzaWMgcHJvZ3JhbW1pbmcgY29uY2VwdHMgYW5kIHRlcm1pbm9sb2d5IHsjcHJvZ3JhbW1pbmctY29uY2VwdHN9CgpXZSBub3cgaW50cm9kdWNlIHNvbWUgYmFzaWMgcHJvZ3JhbW1pbmcgY29uY2VwdHMgYW5kIHRlcm1pbm9sb2d5LiBJbnN0ZWFkIG9mIGFza2luZyB5b3UgdG8gbWVtb3JpemUgYWxsIHRoZXNlIGNvbmNlcHRzIGFuZCB0ZXJtaW5vbG9neSByaWdodCBub3csIHdlJ2xsIGd1aWRlIHlvdSBzbyB0aGF0IHlvdSdsbCAibGVhcm4gYnkgZG9pbmcuIiBUbyBoZWxwIHlvdSBsZWFybiwgd2Ugd2lsbCBhbHdheXMgdXNlIGEgZGlmZmVyZW50IGZvbnQgdG8gZGlzdGluZ3Vpc2ggcmVndWxhciB0ZXh0IGZyb20gYGNvbXB1dGVyX2NvZGVgLiBUaGUgYmVzdCB3YXkgdG8gbWFzdGVyIHRoZXNlIHRvcGljcyBpcywgaW4gb3VyIG9waW5pb25zLCB0aHJvdWdoIFtkZWxpYmVyYXRlIHByYWN0aWNlXShodHRwczovL2phbWVzY2xlYXIuY29tL2RlbGliZXJhdGUtcHJhY3RpY2UtdGhlb3J5KSB3aXRoIFIgYW5kIGxvdHMgb2YgcmVwZXRpdGlvbi4KCiogQmFzaWNzOiAKICAgICsgKkNvbnNvbGUgcGFuZSo6IHdoZXJlIHlvdSBlbnRlciBpbiBjb21tYW5kcy4gCiAgICArICpSdW5uaW5nIGNvZGUqOiB0aGUgYWN0IG9mIHRlbGxpbmcgUiB0byBwZXJmb3JtIGFuIGFjdCBieSBnaXZpbmcgaXQgY29tbWFuZHMgaW4gdGhlIGNvbnNvbGUuCiAgICArICpPYmplY3RzKjogd2hlcmUgdmFsdWVzIGFyZSBzYXZlZCBpbiBSLiBXZSdsbCBzaG93IHlvdSBob3cgdG8gKmFzc2lnbiogdmFsdWVzIHRvIG9iamVjdHMgYW5kIGhvdyB0byBkaXNwbGF5IHRoZSBjb250ZW50cyBvZiBvYmplY3RzLiBcaW5kZXh7b2JqZWN0c30KICAgICsgKkRhdGEgdHlwZXMqOiBpbnRlZ2VycywgZG91Ymxlcy9udW1lcmljcywgbG9naWNhbHMsIGFuZCBjaGFyYWN0ZXJzLiBcaW5kZXh7ZGF0YSB0eXBlc30gSW50ZWdlcnMgYXJlIHZhbHVlcyBsaWtlIC0xLCAwLCAyLCA0MDkyLiBEb3VibGVzIG9yIG51bWVyaWNzIGFyZSBhIGxhcmdlciBzZXQgb2YgdmFsdWVzIGNvbnRhaW5pbmcgYm90aCB0aGUgaW50ZWdlcnMgYnV0IGFsc28gZnJhY3Rpb25zIGFuZCBkZWNpbWFsIHZhbHVlcyBsaWtlIC0yNC45MzIgYW5kIDAuOC4gTG9naWNhbHMgYXJlIGVpdGhlciBgVFJVRWAgb3IgYEZBTFNFYCB3aGlsZSBjaGFyYWN0ZXJzIGFyZSB0ZXh0IHN1Y2ggYXMgImNhbmNlciIsICJob3NwaXRhbCIsICJUaGUgcGF0aWVudCBjb21lcyBmcm9tIHRoZSBjaXR5IGhvc3BpdGFsIiwgYW5kICJNeSBuYW1lIGlzIFBldGVyLiIgTm90ZSB0aGF0IGNoYXJhY3RlcnMgYXJlIG9mdGVuIGRlbm90ZWQgd2l0aCB0aGUgcXVvdGF0aW9uIG1hcmtzIGFyb3VuZCB0aGVtLgoqICpWZWN0b3JzKjogYSBzZXJpZXMgb2YgdmFsdWVzLiAKKiAqRmFjdG9ycyo6ICpjYXRlZ29yaWNhbCBkYXRhKiBhcmUgY29tbW9ubHkgcmVwcmVzZW50ZWQgaW4gUiBhcyBmYWN0b3JzLiAgQ2F0ZWdvcmljYWwgZGF0YSBjYW4gYWxzbyBiZSByZXByZXNlbnRlZCBhcyAqc3RyaW5ncyouIAoqICpEYXRhIGZyYW1lcyo6IHJlY3Rhbmd1bGFyIHNwcmVhZHNoZWV0cy4gVGhleSBhcmUgcmVwcmVzZW50YXRpb25zIG9mIGRhdGFzZXRzIGluIFIgd2hlcmUgdGhlIHJvd3MgY29ycmVzcG9uZCB0byAqb2JzZXJ2YXRpb25zKiBhbmQgdGhlIGNvbHVtbnMgY29ycmVzcG9uZCB0byAqdmFyaWFibGVzKiB0aGF0IGRlc2NyaWJlIHRoZSBvYnNlcnZhdGlvbnMuICAKCgpJZiB5b3UgaGF2ZSB3b3JrZWQgd2l0aCBhIHNwcmVhZHNoZWV0IHN1Y2ggYXMgRXhjZWwgdGhpbmsgdGhlIGRhdGFmcmFtZSBhcyB0aGUgc3ByZWFkc2hlZXQgYW5kIHZlY3RvcnMgYXMgdGhlIGNvbHVtbnMuIAoKIyMjIEVycm9ycywgd2FybmluZ3MsIGFuZCBtZXNzYWdlcyB7I21lc3NhZ2VzfQoKT25lIHRoaW5nIHRoYXQgaW50aW1pZGF0ZXMgbmV3IFIgYW5kIFJTdHVkaW8gdXNlcnMgaXMgaG93IGl0IHJlcG9ydHMgKmVycm9ycyosICp3YXJuaW5ncyosIGFuZCAqbWVzc2FnZXMqLiBSIHJlcG9ydHMgZXJyb3JzLCB3YXJuaW5ncywgYW5kIG1lc3NhZ2VzIGluIGEgZ2xhcmluZyByZWQgZm9udCwgd2hpY2ggbWFrZXMgaXQgc2VlbSBsaWtlIGl0IGlzIHNjb2xkaW5nIHlvdS4gSG93ZXZlciwgc2VlaW5nIHJlZCB0ZXh0IGluIHRoZSBjb25zb2xlIGlzIG5vdCBhbHdheXMgYmFkLgoKUiB3aWxsIHNob3cgcmVkIHRleHQgaW4gdGhlIGNvbnNvbGUgcGFuZSBpbiB0aHJlZSBkaWZmZXJlbnQgc2l0dWF0aW9uczoKCiogKipFcnJvcnMqKjogXGluZGV4e1IhZXJyb3JzfSBXaGVuIHRoZSByZWQgdGV4dCBpcyBhIGxlZ2l0aW1hdGUgZXJyb3IsIGl0IHdpbGwgYmUgcHJlZmFjZWQgd2l0aCAiRXJyb3IgaW7igKYiIGFuZCB3aWxsIHRyeSB0byBleHBsYWluIHdoYXQgd2VudCB3cm9uZy4gR2VuZXJhbGx5IHdoZW4gdGhlcmUncyBhbiBlcnJvciwgdGhlIGNvZGUgd2lsbCBub3QgcnVuLiBGb3IgZXhhbXBsZSwgd2UnbGwgc2VlIGluIFN1YnNlY3Rpb24gXEByZWYocGFja2FnZS11c2UpIGlmIHlvdSBzZWUgYEVycm9yIGluIGdncGxvdCguLi4pIDogY291bGQgbm90IGZpbmQgZnVuY3Rpb24gImdncGxvdCJgLCBpdCBtZWFucyB0aGF0IHRoZSBgZ2dwbG90KClgIGZ1bmN0aW9uIGlzIG5vdCBhY2Nlc3NpYmxlIGJlY2F1c2UgdGhlIHBhY2thZ2UgdGhhdCBjb250YWlucyB0aGUgZnVuY3Rpb24gKGBnZ3Bsb3QyYCkgd2FzIG5vdCBsb2FkZWQgd2l0aCBgbGlicmFyeShnZ3Bsb3QyKWAuIFRodXMgeW91IGNhbm5vdCB1c2UgdGhlIGBnZ3Bsb3QoKWAgZnVuY3Rpb24gd2l0aG91dCB0aGUgYGdncGxvdDJgIHBhY2thZ2UgYmVpbmcgbG9hZGVkIGZpcnN0LgoqICoqV2FybmluZ3MqKjogXGluZGV4e1Ihd2FybmluZ3N9IFdoZW4gdGhlIHJlZCB0ZXh0IGlzIGEgd2FybmluZywgaXQgd2lsbCBiZSBwcmVmYWNlZCB3aXRoICJXYXJuaW5nOiIgYW5kIFIgd2lsbCB0cnkgdG8gZXhwbGFpbiB3aHkgdGhlcmUncyBhIHdhcm5pbmcuIEdlbmVyYWxseSB5b3VyIGNvZGUgd2lsbCBzdGlsbCB3b3JrLCBidXQgd2l0aCBzb21lIGNhdmVhdHMuIEZvciBleGFtcGxlLCB5b3Ugd2lsbCBzZWUgaW4gQ2hhcHRlciBcQHJlZih2aXopIGlmIHlvdSBjcmVhdGUgYSBzY2F0dGVycGxvdCBiYXNlZCBvbiBhIGRhdGFzZXQgd2hlcmUgdHdvIG9mIHRoZSByb3dzIG9mIGRhdGEgaGF2ZSBtaXNzaW5nIGVudHJpZXMgdGhhdCB3b3VsZCBiZSBuZWVkZWQgdG8gY3JlYXRlIHBvaW50cyBpbiB0aGUgc2NhdHRlcnBsb3QsIHlvdSB3aWxsIHNlZSB0aGlzIHdhcm5pbmc6IGBXYXJuaW5nOiBSZW1vdmVkIDIgcm93cyBjb250YWluaW5nIG1pc3NpbmcgdmFsdWVzIChnZW9tX3BvaW50KWAuIFIgd2lsbCBzdGlsbCBwcm9kdWNlIHRoZSBzY2F0dGVycGxvdCB3aXRoIGFsbCB0aGUgcmVtYWluaW5nIG5vbi1taXNzaW5nIHZhbHVlcywgYnV0IGl0IGlzIHdhcm5pbmcgeW91IHRoYXQgdHdvIG9mIHRoZSBwb2ludHMgYXJlbid0IHRoZXJlLgoqICoqTWVzc2FnZXMqKjogXGluZGV4e1IhbWVzc2FnZXN9IFdoZW4gdGhlIHJlZCB0ZXh0IGRvZXNuJ3Qgc3RhcnQgd2l0aCBlaXRoZXIgIkVycm9yIiBvciAiV2FybmluZyIsIGl0J3MgKmp1c3QgYSBmcmllbmRseSBtZXNzYWdlKi4gWW91J2xsIHNlZSB0aGVzZSBtZXNzYWdlcyB3aGVuIHlvdSBsb2FkICpSIHBhY2thZ2VzKiBpbiB0aGUgdXBjb21pbmcgU3Vic2VjdGlvbiBcQHJlZihwYWNrYWdlLWxvYWRpbmcpIG9yIHdoZW4geW91IHJlYWQgZGF0YSBzYXZlZCBpbiBzcHJlYWRzaGVldCBmaWxlcyB3aXRoIHRoZSBgcmVhZF9jc3YoKWAgZnVuY3Rpb24gYXMgeW91J2xsIHNlZSBpbiBDaGFwdGVyIFxAcmVmKHRpZHkpLiBUaGVzZSBhcmUgaGVscGZ1bCBkaWFnbm9zdGljIG1lc3NhZ2VzIGFuZCB0aGV5IGRvbid0IHN0b3AgeW91ciBjb2RlIGZyb20gd29ya2luZy4gQWRkaXRpb25hbGx5LCB5b3UnbGwgc2VlIHRoZXNlIG1lc3NhZ2VzIHdoZW4geW91IGluc3RhbGwgcGFja2FnZXMgdG9vIHVzaW5nIGBpbnN0YWxsLnBhY2thZ2VzKClgIGFzIGRpc2N1c3NlZCBpbiBTdWJzZWN0aW9uIFxAcmVmKHBhY2thZ2UtaW5zdGFsbGF0aW9uKS4KClJlbWVtYmVyLCB3aGVuIHlvdSBzZWUgcmVkIHRleHQgaW4gdGhlIGNvbnNvbGUsICpkb24ndCBwYW5pYyouIEl0IGRvZXNuJ3QgbmVjZXNzYXJpbHkgbWVhbiBhbnl0aGluZyBpcyB3cm9uZy4gUmF0aGVyOgoKKiBJZiB0aGUgdGV4dCBzdGFydHMgd2l0aCAiRXJyb3IiLCBmaWd1cmUgb3V0IHdoYXQncyBjYXVzaW5nIGl0LiA8c3BhbiBzdHlsZT0iY29sb3I6cmVkIj5UaGluayBvZiBlcnJvcnMgYXMgYSByZWQgdHJhZmZpYyBsaWdodDogc29tZXRoaW5nIGlzIHdyb25nITwvc3Bhbj4KKiBJZiB0aGUgdGV4dCBzdGFydHMgd2l0aCAiV2FybmluZyIsIGZpZ3VyZSBvdXQgaWYgaXQncyBzb21ldGhpbmcgdG8gd29ycnkgYWJvdXQuIEZvciBpbnN0YW5jZSwgaWYgeW91IGdldCBhIHdhcm5pbmcgYWJvdXQgbWlzc2luZyB2YWx1ZXMgaW4gYSBzY2F0dGVycGxvdCBhbmQgeW91IGtub3cgdGhlcmUgYXJlIG1pc3NpbmcgdmFsdWVzLCB5b3UncmUgZmluZS4gSWYgdGhhdCdzIHN1cnByaXNpbmcsIGxvb2sgYXQgeW91ciBkYXRhIGFuZCBzZWUgd2hhdCdzIG1pc3NpbmcuIDxzcGFuIHN0eWxlPSJjb2xvcjpnb2xkIj5UaGluayBvZiB3YXJuaW5ncyBhcyBhIHllbGxvdyB0cmFmZmljIGxpZ2h0OiBldmVyeXRoaW5nIGlzIHdvcmtpbmcgZmluZSwgYnV0IHdhdGNoIG91dC9wYXkgYXR0ZW50aW9uLjwvc3Bhbj4KKiBPdGhlcndpc2UsIHRoZSB0ZXh0IGlzIGp1c3QgYSBtZXNzYWdlLiBSZWFkIGl0LCB3YXZlIGJhY2sgYXQgUiwgYW5kIHRoYW5rIGl0IGZvciB0YWxraW5nIHRvIHlvdS4gPHNwYW4gc3R5bGU9ImNvbG9yOmdyZWVuIj5UaGluayBvZiBtZXNzYWdlcyBhcyBhIGdyZWVuIHRyYWZmaWMgbGlnaHQ6IGV2ZXJ5dGhpbmcgaXMgd29ya2luZyBmaW5lIGFuZCBrZWVwIG9uIGdvaW5nITwvc3Bhbj4KCgojIyMgVGlwcyBvbiBsZWFybmluZyB0byBjb2RlIHsjdGlwcy1jb2RlfQoKTGVhcm5pbmcgdG8gY29kZS9wcm9ncmFtIGlzIHF1aXRlIHNpbWlsYXIgdG8gbGVhcm5pbmcgYSBmb3JlaWduIGxhbmd1YWdlLiBJdCBjYW4gYmUgZGF1bnRpbmcgYW5kIGZydXN0cmF0aW5nIGF0IGZpcnN0LiBTdWNoIGZydXN0cmF0aW9ucyBhcmUgY29tbW9uIGFuZCBpdCBpcyBub3JtYWwgdG8gZmVlbCBkaXNjb3VyYWdlZCBhcyB5b3UgbGVhcm4uIEhvd2V2ZXIsIGp1c3QgYXMgd2l0aCBsZWFybmluZyBhIGZvcmVpZ24gbGFuZ3VhZ2UsIGlmIHlvdSBwdXQgaW4gdGhlIGVmZm9ydCBhbmQgYXJlIG5vdCBhZnJhaWQgdG8gbWFrZSBtaXN0YWtlcywgYW55Ym9keSBjYW4gbGVhcm4gYW5kIGltcHJvdmUuIAoKSGVyZSBhcmUgYSBmZXcgdXNlZnVsIHRpcHMgdG8ga2VlcCBpbiBtaW5kIGFzIHlvdSBsZWFybiB0byBwcm9ncmFtOgoKKiAqKlJlbWVtYmVyIHRoYXQgY29tcHV0ZXJzIGFyZSBub3QgYWN0dWFsbHkgdGhhdCBzbWFydCoqOiBZb3UgbWF5IHRoaW5rIHlvdXIgY29tcHV0ZXIgb3Igc21hcnRwaG9uZSBpcyAic21hcnQsIiBidXQgcmVhbGx5IHBlb3BsZSBzcGVudCBhIGxvdCBvZiB0aW1lIGFuZCBlbmVyZ3kgZGVzaWduaW5nIHRoZW0gdG8gYXBwZWFyICJzbWFydC4iIEluIHJlYWxpdHksIHlvdSBoYXZlIHRvIHRlbGwgYSBjb21wdXRlciBldmVyeXRoaW5nIGl0IG5lZWRzIHRvIGRvLiBGdXJ0aGVybW9yZSwgdGhlIGluc3RydWN0aW9ucyB5b3UgZ2l2ZSB5b3VyIGNvbXB1dGVyIGNhbid0IGhhdmUgYW55IG1pc3Rha2VzIGluIHRoZW0sIG5vciBjYW4gdGhleSBiZSBhbWJpZ3VvdXMgaW4gYW55IHdheS4KKiAqKlRha2UgdGhlICJjb3B5LCBwYXN0ZSwgYW5kIHR3ZWFrIiBhcHByb2FjaCoqOiBFc3BlY2lhbGx5IHdoZW4geW91IGxlYXJuIHlvdXIgZmlyc3QgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2Ugb3IgeW91IG5lZWQgdG8gdW5kZXJzdGFuZCBwYXJ0aWN1bGFybHkgY29tcGxpY2F0ZWQgY29kZSwgaXQgaXMgb2Z0ZW4gbXVjaCBlYXNpZXIgdG8gdGFrZSBleGlzdGluZyBjb2RlIHRoYXQgeW91IGtub3cgd29ya3MgYW5kIG1vZGlmeSBpdCB0byBzdWl0IHlvdXIgZW5kcy4gVGhpcyBpcyBhcyBvcHBvc2VkIHRvIHRyeWluZyB0byB0eXBlIG91dCB0aGUgY29kZSBmcm9tIHNjcmF0Y2guIFdlIGNhbGwgdGhpcyB0aGUgKiJjb3B5LCBwYXN0ZSwgYW5kIHR3ZWFrIiogYXBwcm9hY2guIFNvIGVhcmx5IG9uLCB3ZSBzdWdnZXN0IG5vdCB0cnlpbmcgdG8gd3JpdGUgY29kZSBmcm9tIG1lbW9yeSwgYnV0IHJhdGhlciB0YWtlIGV4aXN0aW5nIGV4YW1wbGVzIHdlIGhhdmUgcHJvdmlkZWQgeW91LCB0aGVuIGNvcHksIHBhc3RlLCBhbmQgdHdlYWsgdGhlbSB0byBzdWl0IHlvdXIgZ29hbHMuIEFmdGVyIHlvdSBzdGFydCBmZWVsaW5nIG1vcmUgY29uZmlkZW50LCB5b3UgY2FuIHNsb3dseSBtb3ZlIGF3YXkgZnJvbSB0aGlzIGFwcHJvYWNoIGFuZCB3cml0ZSBjb2RlIGZyb20gc2NyYXRjaC4gVGhpbmsgb2YgdGhlICJjb3B5LCBwYXN0ZSwgYW5kIHR3ZWFrIiBhcHByb2FjaCBhcyB0cmFpbmluZyB3aGVlbHMgZm9yIGEgY2hpbGQgbGVhcm5pbmcgdG8gcmlkZSBhIGJpa2UuIEFmdGVyIGdldHRpbmcgY29tZm9ydGFibGUsIHRoZXkgd29uJ3QgbmVlZCB0aGVtIGFueW1vcmUuIAoqICoqVGhlIGJlc3Qgd2F5IHRvIGxlYXJuIHRvIGNvZGUgaXMgYnkgZG9pbmcqKjogUmF0aGVyIHRoYW4gbGVhcm5pbmcgdG8gY29kZSBmb3IgaXRzIG93biBzYWtlLCB3ZSBmaW5kIHRoYXQgbGVhcm5pbmcgdG8gY29kZSBnb2VzIG11Y2ggc21vb3RoZXIgd2hlbiB5b3UgaGF2ZSBhIGdvYWwgaW4gbWluZCBvciB3aGVuIHlvdSBhcmUgd29ya2luZyBvbiBhIHBhcnRpY3VsYXIgcHJvamVjdCwgbGlrZSBhbmFseXppbmcgZGF0YSB0aGF0IHlvdSBhcmUgaW50ZXJlc3RlZCBpbiBhbmQgdGhhdCBpcyBpbXBvcnRhbnQgdG8geW91LiAKKiAqKlByYWN0aWNlIGlzIGtleSoqOiAgSnVzdCBhcyB0aGUgb25seSBtZXRob2QgdG8gaW1wcm92ZSB5b3VyIGZvcmVpZ24gbGFuZ3VhZ2Ugc2tpbGxzIGlzIHRocm91Z2ggbG90cyBvZiBwcmFjdGljZSBhbmQgc3BlYWtpbmcsIHRoZSBvbmx5IG1ldGhvZCB0byBpbXByb3ZpbmcgeW91ciBjb2Rpbmcgc2tpbGxzIGlzIHRocm91Z2ggbG90cyBvZiBwcmFjdGljZS4gRG9uJ3Qgd29ycnksIGhvd2V2ZXIsIHdlJ2xsIGdpdmUgeW91IHBsZW50eSBvZiBvcHBvcnR1bml0aWVzIHRvIGRvIHNvIQoKCgoKCiMjIFdoYXQgYXJlIFIgcGFja2FnZXM/IHsjcGFja2FnZXN9CgpBbm90aGVyIHBvaW50IG9mIGNvbmZ1c2lvbiB3aXRoIG1hbnkgbmV3IFIgdXNlcnMgaXMgdGhlIGlkZWEgb2YgYW4gUiBwYWNrYWdlLiBSIHBhY2thZ2VzICBleHRlbmQgdGhlIGZ1bmN0aW9uYWxpdHkgb2YgUiBieSBwcm92aWRpbmcgYWRkaXRpb25hbCBmdW5jdGlvbnMsIGRhdGEsIGFuZCBkb2N1bWVudGF0aW9uLiBUaGV5IGFyZSB3cml0dGVuIGJ5IGEgd29ybGR3aWRlIGNvbW11bml0eSBvZiBSIHVzZXJzIGFuZCBjYW4gYmUgZG93bmxvYWRlZCBmb3IgZnJlZSBmcm9tIHRoZSBpbnRlcm5ldC4gCgpGb3IgZXhhbXBsZSwgYW1vbmcgdGhlIG1hbnkgcGFja2FnZXMgd2Ugd2lsbCB1c2UgaW4gdGhpcyBib29rIGFyZSB0aGUgYGdncGxvdDJgIHBhY2thZ2UsIHRoZSBgZHBseXJgIHBhY2thZ2UgIGZvciBkYXRhIHdyYW5nbGluZyBhbmQgbWFueSBvdGhlcnMuIFRoZXJlIGFyZSBzb21lIHBhY2thZ2VzIHRoYXQgaW5jbHVkZSBzZXZlcmFsIG90aGVyIHBhY2thZ2VzLiBUaGlzIGlzIHRoZSBjYXNlIHdpdGggYHRpZHl2ZXJzZWAsIHdoaWNoIGluY2x1ZGVzIG1hbnkgb2YgdGhlIHBhY2thZ2VzIG5lZWRlZCBmb3IgdGhlIHVzdWFsIGRhdGEgc2NpZW5jZSB0YXNrcwoKQSBnb29kIGFuYWxvZ3kgZm9yIFIgcGFja2FnZXMgIGlzIHRoZXkgYXJlIGxpa2UgYXBwcyB5b3UgY2FuIGRvd25sb2FkIG9udG8gYSBtb2JpbGUgcGhvbmU6CgohW0FuYWxvZ3kgb2YgUiB2ZXJzdXMgUiBwYWNrYWdlcy5dKC4uL0ZpZ3Mvcl92c19yX3BhY2thZ2VzLnBuZykKClNvIFIgaXMgbGlrZSBhIG5ldyBtb2JpbGUgcGhvbmU6IHdoaWxlIGl0IGhhcyBhIGNlcnRhaW4gYW1vdW50IG9mIGZlYXR1cmVzIHdoZW4geW91IHVzZSBpdCBmb3IgdGhlIGZpcnN0IHRpbWUsIGl0IGRvZXNuJ3QgaGF2ZSBldmVyeXRoaW5nLiBSIHBhY2thZ2VzIGFyZSBsaWtlIHRoZSBhcHBzIHlvdSBjYW4gZG93bmxvYWQgb250byB5b3VyIHBob25lIGZyb20gQXBwbGUncyBBcHAgU3RvcmUgb3IgQW5kcm9pZCdzIEdvb2dsZSBQbGF5LiAKCkxldCdzIGNvbnRpbnVlIHRoaXMgYW5hbG9neSBieSBjb25zaWRlcmluZyB0aGUgSW5zdGFncmFtIGFwcCBmb3IgZWRpdGluZyBhbmQgc2hhcmluZyBwaWN0dXJlcy4gU2F5IHlvdSBoYXZlIHB1cmNoYXNlZCBhIG5ldyBwaG9uZSBhbmQgeW91IHdvdWxkIGxpa2UgdG8gc2hhcmUgYSBwaG90byB5b3UgaGF2ZSBqdXN0IHRha2VuIHdpdGggZnJpZW5kcyBvbiBJbnN0YWdyYW0uIFlvdSBuZWVkIHRvOgoKMS4gKkluc3RhbGwgdGhlIGFwcCo6IFNpbmNlIHlvdXIgcGhvbmUgaXMgbmV3IGFuZCBkb2VzIG5vdCBpbmNsdWRlIHRoZSBJbnN0YWdyYW0gYXBwLCB5b3UgbmVlZCB0byBkb3dubG9hZCB0aGUgYXBwIGZyb20gZWl0aGVyIHRoZSBBcHAgU3RvcmUgb3IgR29vZ2xlIFBsYXkuIFlvdSBkbyB0aGlzIG9uY2UgYW5kIHlvdSdyZSBzZXQgZm9yIHRoZSB0aW1lIGJlaW5nLiBZb3UgbWlnaHQgbmVlZCB0byBkbyB0aGlzIGFnYWluIGluIHRoZSBmdXR1cmUgd2hlbiB0aGVyZSBpcyBhbiB1cGRhdGUgdG8gdGhlIGFwcC4KMS4gKk9wZW4gdGhlIGFwcCo6IEFmdGVyIHlvdSd2ZSBpbnN0YWxsZWQgSW5zdGFncmFtLCB5b3UgbmVlZCB0byBvcGVuIGl0LgoKT25jZSBJbnN0YWdyYW0gaXMgb3BlbiBvbiB5b3VyIHBob25lLCB5b3UgY2FuIHRoZW4gcHJvY2VlZCB0byBzaGFyZSB5b3VyIHBob3RvIHdpdGggeW91ciBmcmllbmRzIGFuZCBmYW1pbHkuIFRoZSBwcm9jZXNzIGlzIHZlcnkgc2ltaWxhciBmb3IgdXNpbmcgYW4gUiBwYWNrYWdlLiBZb3UgbmVlZCB0bzoKCjEuICpJbnN0YWxsIHRoZSBwYWNrYWdlKjogVGhpcyBpcyBsaWtlIGluc3RhbGxpbmcgYW4gYXBwIG9uIHlvdXIgcGhvbmUuIE1vc3QgcGFja2FnZXMgYXJlIG5vdCBpbnN0YWxsZWQgYnkgZGVmYXVsdCB3aGVuIHlvdSBpbnN0YWxsIFIgYW5kIFJTdHVkaW8uIFRodXMgaWYgeW91IHdhbnQgdG8gdXNlIGEgcGFja2FnZSBmb3IgdGhlIGZpcnN0IHRpbWUsIHlvdSBuZWVkIHRvIGluc3RhbGwgaXQgZmlyc3QuIE9uY2UgeW91J3ZlIGluc3RhbGxlZCBhIHBhY2thZ2UsIHlvdSBsaWtlbHkgd29uJ3QgaW5zdGFsbCBpdCBhZ2FpbiB1bmxlc3MgeW91IHdhbnQgdG8gdXBkYXRlIGl0IHRvIGEgbmV3ZXIgdmVyc2lvbi4KMS4gKiJMb2FkIiB0aGUgcGFja2FnZSo6ICJMb2FkaW5nIiBhIHBhY2thZ2UgaXMgbGlrZSBvcGVuaW5nIGFuIGFwcCBvbiB5b3VyIHBob25lLiBQYWNrYWdlcyBhcmUgbm90ICJsb2FkZWQiIGJ5IGRlZmF1bHQgd2hlbiB5b3Ugc3RhcnQgUlN0dWRpbyBvbiB5b3VyIGNvbXB1dGVyOyB5b3UgbmVlZCB0byAibG9hZCIgZWFjaCBwYWNrYWdlIHlvdSB3YW50IHRvIHVzZSBldmVyeSB0aW1lIHlvdSBzdGFydCBSU3R1ZGlvLgoKTGV0J3MgcGVyZm9ybSB0aGVzZSB0d28gc3RlcHMgZm9yIHRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlIHRoYXQgaW5jbHVkZXMgbWFueSBvdGhlciBwYWNrYWdlcywgYXMgJ2dncGxvdDInIGRhdGEgdmlzdWFsaXphdGlvbi4KCiMjIyBQYWNrYWdlIGluc3RhbGxhdGlvbiB7I3BhY2thZ2UtaW5zdGFsbGF0aW9ufQoKCgphKSBDbGljayBvbiB0aGUgIlBhY2thZ2VzIiB0YWIuCmEpIFR5cGUgdGhlIG5hbWUgb2YgdGhlIHBhY2thZ2UgdW5kZXIgIlBhY2thZ2VzIChzZXBhcmF0ZSBtdWx0aXBsZSB3aXRoIHNwYWNlIG9yIGNvbW1hKToiIEluIHRoaXMgY2FzZSwgdHlwZSBgdGlkeXZlcnNlYC4KYSkgQ2xpY2sgb24gIkluc3RhbGwiIG5leHQgdG8gVXBkYXRlLgphKSBDbGljayAiSW5zdGFsbC4iICAKCgohWyJUaWR5dmVyc2UgcGFja2FnZSBpbnN0YWxsYXRpb24iXSguLi9GaWdzL3RpZHl2ZXJzZTAxLnBuZykKCgpBbiBhbHRlcm5hdGl2ZSBidXQgc2xpZ2h0bHkgbGVzcyBjb252ZW5pZW50IHdheSB0byBpbnN0YWxsIGEgcGFja2FnZSBpcyBieSB0eXBpbmcgYGluc3RhbGwucGFja2FnZXMoInRpZHl2ZXJzZSIpYCBpbiB0aGUgY29uc29sZSBwYW5lIG9mIFJTdHVkaW8gYW5kIHByZXNzaW5nIFJldHVybi9FbnRlciBvbiB5b3VyIGtleWJvYXJkLiBOb3RlIHlvdSBtdXN0IGluY2x1ZGUgdGhlIHF1b3RhdGlvbiBtYXJrcyBhcm91bmQgdGhlIG5hbWUgb2YgdGhlIHBhY2thZ2UuCgpNdWNoIGxpa2UgYW4gYXBwIG9uIHlvdXIgcGhvbmUsIHlvdSBvbmx5IGhhdmUgdG8gaW5zdGFsbCBhIHBhY2thZ2Ugb25jZS4gSG93ZXZlciwgaWYgeW91IHdhbnQgdG8gdXBkYXRlIGEgcHJldmlvdXNseSBpbnN0YWxsZWQgcGFja2FnZSB0byBhIG5ld2VyIHZlcnNpb24sIHlvdSBuZWVkIHRvIHJlaW5zdGFsbCBpdCBieSByZXBlYXRpbmcgdGhlIGVhcmxpZXIgc3RlcHMuCgoKClJlcGVhdCB0aGUgZWFybGllciBpbnN0YWxsYXRpb24gc3RlcHMsIGJ1dCBmb3IgdGhlIGBwYWxtZXJwZW5ndWluc2AsIGBOSEFORVNgLCBhbmQgYGphbml0b3JgIHBhY2thZ2VzLiBUaGlzIHdpbGwgaW5zdGFsbCB0aGUgZWFybGllciBtZW50aW9uZWQgcGFja2FnZXMuIFdlJ2xsIHVzZSB0aGVzZSBwYWNrYWdlcyAoYW5kIG1vcmUpIGR1cmluZyB0aGUgY291cnNlLgoKIApOb3RlIHRoYXQgaWYgeW91J2QgbGlrZSB5b3VyIG91dHB1dCBvbiB5b3VyIGNvbXB1dGVyIHRvIG1hdGNoIHVwIGV4YWN0bHkgd2l0aCB0aGUgb3V0cHV0IHByZXNlbnRlZCB0aHJvdWdob3V0IHRoZSBib29rLCB5b3UgbWF5IHdhbnQgdG8gdXNlIHRoZSBleGFjdCB2ZXJzaW9ucyBvZiB0aGUgcGFja2FnZXMgdGhhdCB3ZSB1c2VkLiBZb3UgY2FuIGZpbmQgYSBmdWxsIGxpc3Rpbmcgb2YgdGhlc2UgcGFja2FnZXMgYW5kIHRoZWlyIHZlcnNpb25zIGluIEFwcGVuZGl4IFxAcmVmKGFwcGVuZGl4RSkuIFRoaXMgbGlrZWx5IHdvbid0IGJlIHJlbGV2YW50IGZvciBub3ZpY2VzLCBidXQgd2UgaW5jbHVkZWQgaXQgZm9yIHJlcHJvZHVjaWJpbGl0eSByZWFzb25zLgoKIyMjIFBhY2thZ2UgbG9hZGluZyB7I3BhY2thZ2UtbG9hZGluZ30KClJlY2FsbCB0aGF0IGFmdGVyIHlvdSd2ZSBpbnN0YWxsZWQgYSBwYWNrYWdlLCB5b3UgbmVlZCB0byAibG9hZCBpdC4iIEluIG90aGVyIHdvcmRzLCB5b3UgbmVlZCB0byAib3BlbiBpdC4iIFdlIGRvIHRoaXMgYnkgdXNpbmcgdGhlIGBsaWJyYXJ5KClgIGNvbW1hbmQuIFxpbmRleHtSIHBhY2thZ2VzIWxvYWRpbmd9IAoKRm9yIGV4YW1wbGUsIHRvIGxvYWQgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlLCBydW4gdGhlIGZvbGxvd2luZyBjb2RlIGluIHRoZSBjb25zb2xlIHBhbmUuIFdoYXQgZG8gd2UgbWVhbiBieSAicnVuIHRoZSBmb2xsb3dpbmcgY29kZSI/IEVpdGhlciB0eXBlIG9yIGNvcHktYW5kLXBhc3RlIHRoZSBmb2xsb3dpbmcgY29kZSBpbnRvIHRoZSBjb25zb2xlIHBhbmUgYW5kIHRoZW4gaGl0IHRoZSBFbnRlciBrZXkuIAoKYGBge3IsIGV2YWw9RkFMU0V9CmxpYnJhcnkoZ2dwbG90MikKYGBgCgpJZiBhZnRlciBydW5uaW5nIHRoZSBlYXJsaWVyIGNvZGUsIGEgYmxpbmtpbmcgY3Vyc29yIHJldHVybnMgbmV4dCB0byB0aGUgYD5gICJwcm9tcHQiIHNpZ24sIGl0IG1lYW5zIHlvdSB3ZXJlIHN1Y2Nlc3NmdWwgYW5kIHRoZSBgZ2dwbG90MmAgcGFja2FnZSBpcyBub3cgbG9hZGVkIGFuZCByZWFkeSB0byB1c2UuIElmLCBob3dldmVyLCB5b3UgZ2V0IGEgcmVkICJlcnJvciBtZXNzYWdlIiB0aGF0IHJlYWRzIGAuLi5gIAoKYGBgCkVycm9yIGluIGxpYnJhcnkoZ2dwbG90MikgOiB0aGVyZSBpcyBubyBwYWNrYWdlIGNhbGxlZCDigJhnZ3Bsb3Qy4oCZCmBgYAoKYC4uLmAgaXQgbWVhbnMgdGhhdCB5b3UgZGlkbid0IHN1Y2Nlc3NmdWxseSBpbnN0YWxsIGl0LiBUaGlzIGlzIGFuIGV4YW1wbGUgb2YgYW4gImVycm9yIG1lc3NhZ2UiIC4gSWYgeW91IGdldCB0aGlzIGVycm9yIG1lc3NhZ2UsIGdvIGJhY2sgdG8gIG9mIFBhY2thZ2UgSW5zdGFsbGF0aW9uIG9uIFIgcGFja2FnZSBpbnN0YWxsYXRpb24gYW5kIG1ha2Ugc3VyZSB0byBpbnN0YWxsIHRoZSBgdGlkeXZlcnNlYCBwYWNrYWdlIGJlZm9yZSBwcm9jZWVkaW5nLiAKCgoKIyMjIFBhY2thZ2UgdXNlIHsjcGFja2FnZS11c2V9CgpPbmUgdmVyeSBjb21tb24gbWlzdGFrZSBuZXcgUiB1c2VycyBtYWtlIHdoZW4gd2FudGluZyB0byB1c2UgcGFydGljdWxhciBwYWNrYWdlcyBpcyB0aGV5IGZvcmdldCB0byAibG9hZCIgdGhlbSBmaXJzdCBieSB1c2luZyB0aGUgYGxpYnJhcnkoKWAgY29tbWFuZCB3ZSBqdXN0IHNhdy4gUmVtZW1iZXI6ICp5b3UgaGF2ZSB0byBsb2FkIGVhY2ggcGFja2FnZSB5b3Ugd2FudCB0byB1c2UgZXZlcnkgdGltZSB5b3Ugc3RhcnQgUlN0dWRpby4qIElmIHlvdSBkb24ndCBmaXJzdCAibG9hZCIgYSBwYWNrYWdlLCBidXQgYXR0ZW1wdCB0byB1c2Ugb25lIG9mIGl0cyBmZWF0dXJlcywgeW91J2xsIHNlZSBhbiBlcnJvciBtZXNzYWdlIHNpbWlsYXIgdG86CgpgYGAKRXJyb3I6IGNvdWxkIG5vdCBmaW5kIGZ1bmN0aW9uCmBgYAoKVGhpcyBpcyBhIGRpZmZlcmVudCBlcnJvciBtZXNzYWdlIHRoYW4gdGhlIG9uZSB5b3UganVzdCBzYXcgb24gYSBwYWNrYWdlIG5vdCBoYXZpbmcgYmVlbiBpbnN0YWxsZWQgeWV0LiBSIGlzIHRlbGxpbmcgeW91IHRoYXQgeW91IGFyZSB0cnlpbmcgdG8gdXNlIGEgZnVuY3Rpb24gaW4gYSBwYWNrYWdlIHRoYXQgaGFzIG5vdCB5ZXQgYmVlbiAibG9hZGVkLiIgUiBkb2Vzbid0IGtub3cgd2hlcmUgdG8gZmluZCB0aGUgZnVuY3Rpb24geW91IGFyZSB1c2luZy4gQWxtb3N0IGFsbCBuZXcgdXNlcnMgZm9yZ2V0IHRvIGRvIHRoaXMgd2hlbiBzdGFydGluZyBvdXQsIGFuZCBpdCBpcyBhIGxpdHRsZSBhbm5veWluZyB0byBnZXQgdXNlZCB0byBkb2luZyBpdC4gSG93ZXZlciwgeW91J2xsIHJlbWVtYmVyIHdpdGggcHJhY3RpY2UgYW5kIGFmdGVyIHNvbWUgdGltZSBpdCB3aWxsIGJlY29tZSBzZWNvbmQgbmF0dXJlIGZvciB5b3UuCg==